#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <sys/stat.h>
#include <iomanip>
#include <cstring>
#include <assert.h>
#include <dirent.h>
#include <vector>
#include <typeinfo>
using namespace std;

// options
enum OPTION
{
    OPT_h,
    OPT_A,
    OPT_b,
    OPT_r,
    OPT_s,
    OPT_NUM
};

// gobal variable
int g_option[OPT_NUM];
vector<string> g_dirPath;
int dirFd; // the file descriptor  associated with the directory
// vector<vector<int> > line_printed(100,vector<int>(3));
int **line_printed;
string *path_printed;
int counter;
string suffix;
/**
 * 判断输入的字符串是不是文件（0），文件夹（1），mode（2），都不是则为3
 */
int is_file(const char *pathname);

int *compute_line_number(const char *pathname);
void print(int mode);
void print_help();
void get_option(const char *strOption);
void do_lc(const char *path);
void get_path(const char *strPath);
// vector<string> get_files(const char *path);

int main(int argc, char *argv[])
{
    // global initialize
    counter = 0;
    suffix = "";
    line_printed = new int *[100];
    path_printed = new string[100];

    memset(g_option, 0, sizeof(int) * OPT_NUM);
    // 传入的参数数量
    int arg_count = argc-1;
    // if(strcmp(argv[1],"-h") || strcmp(argv[1],"--help")){
    //     print_help();
    // }else{

    // }
    // process option
    while (--argc != 0)
    {
        if ('-' == argv[argc][0])
        {
            get_option(argv[argc]);
        }
        else
        {
            get_path(argv[argc]);
        }
    }

    // -s 特殊操作
    if (g_option[OPT_s] == 1 && strcmp(argv[arg_count - g_dirPath.size()], "-s") == 0)
    {
        suffix = "." + g_dirPath.back();
        g_dirPath.pop_back();
    }

    if (g_dirPath.empty())
    {
        // 打印help
        print(2);
    }
    else
    {
        for (auto it = g_dirPath.begin(); it != g_dirPath.end();)
        {
            // cout<<"line:72  "<<it->c_str()<<endl;
            do_lc(it->c_str());
            ++it;
        }
    }
    // 打印
    print(2);
    return 0;
}

int is_file(const char *pathname)
{
    struct stat buf;
    int result;
    result = stat(pathname, &buf);
    if (S_IFDIR & buf.st_mode)
    {
        // 文件夹
        // cout<<"folder"<<endl;
        return 1;
    }
    else if (S_IFREG & buf.st_mode)
    {
        // 文件
        return 0;
    }
    else
    {
        int a = 0;
        return 2;
    }
}

int *compute_line_number(const char *pathname)
{
    int *arr = new int[3];

    ifstream infile(pathname);
    char str[1000];
    // 空行计数
    int null_count = 0;
    // 非空行计数
    int content_count = 0;
    // 总行数计数
    int total_count = 0;

    if (infile.is_open())
        while (!infile.eof())
        {
            infile.getline(str, sizeof(str));
            if (str != nullptr && (str[0] == '\r' || str[0] == '\n' || (int)(str[0]) == 0))
            {
                // 为空(对应ASCII码为13,10,0)
                null_count++;
            }
            else
            {
                // 不为空
                content_count++;
            }
            total_count = content_count + null_count;
        }
    // cout << "The null count is " << null_count << endl;
    // cout << "The content count is " << content_count << endl;
    // cout << "The total line number is: " << total_count << endl;

    arr[0] = content_count;
    arr[1] = null_count;
    arr[2] = total_count;

    return arr;
}

void print(int mode)
{   
    if (g_option[OPT_b] == 1)
    {
        // -b 忽略空行
        mode = 0;
    }
    else if (mode < 0 && mode > 2)
    {
        mode = 2;
    }

    if (g_option[OPT_h] || counter == 0)
    {
        print_help();
    }
    else
    {
        cout << left << setw(10) << "line"
             << "file" << endl;
        cout << left << setw(10) << "----"
             << "----" << endl;

        // 计算总和
        int sum = 0;
        for (int i = 0; i < counter; i++)
        {
            if (g_option[OPT_s] && path_printed[i].find(suffix) > path_printed[i].length())
                continue;

            sum += line_printed[i][mode];
        }
        if (g_option[OPT_A] && !(counter == 1 && is_file(path_printed[0].data()) == 0))
        {
            // -A --all
            cout << right << setw(4) << sum <<"      " << "total" << endl;
        }
        else
        {

            // 正常模式
            int temp = 0;
            for (int i = 0; i < counter; i++)
            {
                if ((g_option[OPT_s] == 1) && path_printed[i].find(suffix) > path_printed[i].length())
                {   
                    temp++;
                    continue;
                }
                cout << right << setw(4) << line_printed[i][mode] <<"      "<< path_printed[i] << endl;
            }
            counter -= temp;
            if (counter > 1)
                cout << right << setw(4) << sum <<"      "<< "total" << endl;
        }

        cout << endl;
    }
}

void print_help()
{
    int blank = 30;
    cout << "Usage: lc [OPTION] ... [FILE | DIR] ..." << endl;
    cout << "Print newline counts for each FILE or DIR, and a total line if more than one FILE is specified." << endl
         << endl;
    cout << "With no FILE, or when FILE is -, read standard input." << endl
         << endl;
    cout << "The options below may be used to control print msg" << endl;
    cout << setw(5) << "" << left << setw(blank) << "-A, --all"
         << "print the total line number only" << endl;
    cout << setw(5) << "" << left << setw(blank) << "-b"
         << "ignore the Blank line when counting" << endl;
    cout << setw(5) << "" << left << setw(blank) << "-r"
         << "count directory Recursively" << endl;
    cout << setw(5) << "" << left << setw(blank) << "-s, --suffix=FILE-SUFFIX"
         << "only count the file with specified Suffix" << endl;
    cout << setw(5) << "" << left << setw(blank) << "-h, --help"
         << "display this Help and exit" << endl;
    exit(0);
}

void get_option(const char *strOption)
{
    assert(strOption);
    if (strcmp(strOption, "-h") == 0 || strcmp(strOption, "--help") == 0)
    {
        g_option[OPT_h] = 1;
    }
    else if (strcmp(strOption, "-A") == 0 || strcmp(strOption, "--all") == 0)
    {
        g_option[OPT_A] = 1;
    }
    else if (strcmp(strOption, "-b") == 0)
    {
        g_option[OPT_b] = 1;
    }
    else if (strcmp(strOption, "-r") == 0)
    {
        g_option[OPT_r] = 1;
    }
    else if (strcmp(strOption, "-s") == 0 && g_option[OPT_s]==0)
    {
        
        g_option[OPT_s] = 1;
    }
    else if (((string)strOption).find("--suffix") == 0 && g_option[OPT_s]==0)
    {
        string temp = strOption;
        if (temp.length() <9){
            print_help();
        }
        suffix = "." + temp.substr(9, temp.length() - 9);
        g_option[OPT_s] = 1;
    }
    else{
        print_help();
    }
}

void get_path(const char *strPath)
{
    assert(strPath);
    g_dirPath.push_back(strPath);
}

void do_lc(const char *path)
{
    assert(path);

    DIR *p_dir;
    struct dirent *p_next;
    vector<string> list;
    // 0: file; 1:folder;
    int flag = is_file(path);
    if (flag == 0)
    {
        // 文件
        int *lines = new int[3];
        lines = compute_line_number(path);
        string pathName = path;
        // print(lines, pathName, 0);

        line_printed[counter] = lines;
        path_printed[counter] = pathName;
        counter++;
    }
    else if (flag == 1)
    {
        // 文件夹
        if ((p_dir = opendir(path)) == NULL)
        {
            perror("opendir error");
            exit(1);
        }

        if ((dirFd = dirfd(p_dir)) == -1)
        {
            perror("dirfd error");
            exit(0);
        }

        while ((p_next = readdir(p_dir)) != NULL)
        {
            // cout << "p_next->d_name: " << p_next->d_name << endl;
            // process option -a
            string temp = path;
            string connector = "/";
            if (temp.back() == '/')
                connector = "";
            string pathname = temp + connector + p_next->d_name;

            if (is_file(pathname.data()) == 1)
            {
                // 当不采用-r模式时，所有文件夹都跳过
                // 当采用-r模式时，除了"."和".."之外的文件夹都跳过
                if (g_option[OPT_r] == 0 || (strcmp(p_next->d_name, ".") == 0 || strcmp(p_next->d_name, "..") == 0))
                {
                    continue;
                }
            }
            list.push_back(pathname);
        }
        for (int i = 0; i < list.size(); i++)
        {
            do_lc(list[i].data());
        }
    }
}


// #include <cstdio>
// #include <cstdlib>
// #include <iostream>
// #include <fstream>
// #include <sys/stat.h>
// #include <iomanip>
// #include <cstring>
// #include <cassert>
// #include <dirent.h>
// #include <vector>
// #include <typeinfo>
// using namespace std;

// // options
// enum OPTION
// {
//     OPT_h,
//     OPT_A,
//     OPT_b,
//     OPT_r,
//     OPT_s,
//     OPT_NUM
// };

// // gobal variable
// int g_option[OPT_NUM];
// vector<string> g_dirPath;
// int dirFd; // the file descriptor  associated with the directory
// // vector<vector<int> > line_printed(100,vector<int>(3));
// int **line_printed;
// string *path_printed;
// int counter;
// string suffix;

// /**
//  * 判断输入的字符串是不是文件（0），文件夹（1），mode（2），都不是则为3
//  */
// int is_file(const char *pathname);

// int *compute_line_number(const char *pathname);
// void print(int mode);
// void print_help();
// void get_option(const char *strOption);
// void do_lc(const char *path);
// void get_path(const char *strPath);
// // vector<string> get_files(const char *path);

// int main(int argc, char *argv[])
// {
//     // global initialize
//     counter = 0;
//     suffix = "";
//     line_printed = new int *[100];
//     path_printed = new string[100];

//     memset(g_option, 0, sizeof(int) * OPT_NUM);
//     // 传入的参数数量
//     int arg_count = argc-1;
//     // if(strcmp(argv[1],"-h") || strcmp(argv[1],"--help")){
//     //     print_help();
//     // }else{

//     // }
//     // process option
//     while (--argc != 0)
//     {
//         if ('-' == argv[argc][0])
//         {
//             get_option(argv[argc]);
//         }
//         else
//         {
//             get_path(argv[argc]);
//         }
//     }

//     // -s 特殊操作
//     if (g_option[OPT_s] == 1 && strcmp(argv[arg_count - g_dirPath.size()], "-s") == 0)
//     {
//         suffix = "." + g_dirPath.back();
//         g_dirPath.pop_back();
//     }

//     if (g_dirPath.empty())
//     {
//         // 打印help
//         print(2);
//     }
//     else
//     {
//         for (auto it = g_dirPath.begin(); it != g_dirPath.end();)
//         {
//             // cout<<"line:72  "<<it->c_str()<<endl;
//             do_lc(it->c_str());
//             ++it;
//         }
//     }
//     // 打印
//     print(2);
//     return 0;
// }

// int is_file(const char *pathname)
// {
//     struct stat buf;
//     int result;
//     result = stat(pathname, &buf);
//     if (S_IFDIR & buf.st_mode)
//     {
//         // 文件夹
//         // cout<<"folder"<<endl;
//         return 1;
//     }
//     else if (S_IFREG & buf.st_mode)
//     {
//         // 文件
//         return 0;
//     }
//     else
//     {
//         int a = 0;
//         return 2;
//     }
// }

// int *compute_line_number(const char *pathname)
// {
//     int *arr = new int[3];

//     ifstream infile(pathname);
//     char str[1000];
//     // 空行计数
//     int null_count = 0;
//     // 非空行计数
//     int content_count = 0;
//     // 总行数计数
//     int total_count = 0;

//     if (infile.is_open())
//         while (!infile.eof())
//         {
//             infile.getline(str, sizeof(str));
//             if (str != nullptr && (str[0] == '\r' || str[0] == '\n' || (int)(str[0]) == 0))
//             {
//                 // 为空(对应ASCII码为13,10,0)
//                 null_count++;
//             }
//             else
//             {
//                 // 不为空
//                 content_count++;
//             }
//             total_count = content_count + null_count;
//         }
//     // cout << "The null count is " << null_count << endl;
//     // cout << "The content count is " << content_count << endl;
//     // cout << "The total line number is: " << total_count << endl;

//     arr[0] = content_count;
//     arr[1] = null_count;
//     arr[2] = total_count;

//     return arr;
// }

// void print(int mode)
// {   
//     if (g_option[OPT_b] == 1)
//     {
//         // -b 忽略空行
//         mode = 0;
//     }
//     else if (mode < 0 && mode > 2)
//     {
//         mode = 2;
//     }

//     if (g_option[OPT_h] || counter == 0)
//     {
//         print_help();
//     }
//     else
//     {
//         cout << left << setw(10) << "line"
//              << "file" << endl;
//         cout << left << setw(10) << "----"
//              << "----" << endl;

//         // 计算总和
//         int sum = 0;
//         for (int i = 0; i < counter; i++)
//         {
//             if (g_option[OPT_s] && path_printed[i].find(suffix) > path_printed[i].length())
//                 continue;

//             sum += line_printed[i][mode];
//         }
//         if (g_option[OPT_A] && !(counter == 1 && is_file(path_printed[0].data())))
//         {
//             // -A --all
//             cout << right << setw(4) << sum <<"      " << "total" << endl;
//         }
//         else
//         {

//             // 正常模式
//             for (int i = 0; i < counter; i++)
//             {
//                 if ((g_option[OPT_s] == 1) && path_printed[i].find(suffix) > path_printed[i].length())
//                 {
//                     continue;
//                 }
//                 cout << right << setw(4) << line_printed[i][mode] <<"      "<< path_printed[i] << endl;
//             }
//             if (counter > 1)
//                 cout << right << setw(4) << sum <<"      "<< "total" << endl;
//         }

//         cout << endl;
//     }
// }

// void print_help()
// {
//     int blank = 30;
//     cout << "Usage: lc [OPTION] ... [FILE | DIR] ..." << endl;
//     cout << "Print newline counts for each FILE or DIR, and a total line if more than one FILE is specified." << endl
//          << endl;
//     cout << "With no FILE, or when FILE is -, read standard input." << endl
//          << endl;
//     cout << "The options below may be used to control print msg" << endl;
//     cout << setw(5) << "" << left << setw(blank) << "-A, --all"
//          << "print the total line number only" << endl;
//     cout << setw(5) << "" << left << setw(blank) << "-b"
//          << "ignore the Blank line when counting" << endl;
//     cout << setw(5) << "" << left << setw(blank) << "-r"
//          << "count directory Recursively" << endl;
//     cout << setw(5) << "" << left << setw(blank) << "-s, --suffix=FILE-SUFFIX"
//          << "only count the file with specified Suffix" << endl;
//     cout << setw(5) << "" << left << setw(blank) << "-h, --help"
//          << "display this Help and exit" << endl;
//     exit(0);
// }

// void get_option(const char *strOption)
// {
//     assert(strOption);
//     if (strcmp(strOption, "-h") == 0 || strcmp(strOption, "--help") == 0)
//     {
//         g_option[OPT_h] = 1;
//     }
//     else if (strcmp(strOption, "-A") == 0 || strcmp(strOption, "--all") == 0)
//     {
//         g_option[OPT_A] = 1;
//     }
//     else if (strcmp(strOption, "-b") == 0)
//     {
//         g_option[OPT_b] = 1;
//     }
//     else if (strcmp(strOption, "-r") == 0)
//     {
//         g_option[OPT_r] = 1;
//     }
//     else if (strcmp(strOption, "-s") == 0 && g_option[OPT_s]==0)
//     {
        
//         g_option[OPT_s] = 1;
//     }
//     else if (((string)strOption).find("--suffix") == 0 && g_option[OPT_s]==0)
//     {
//         string temp = strOption;
//         if (temp.length() <9){
//             print_help();
//         }
//         suffix = "." + temp.substr(9, temp.length() - 9);
//         g_option[OPT_s] = 1;
//     }
//     else{
//         print_help();
//     }
// }

// void get_path(const char *strPath)
// {
//     assert(strPath);
//     g_dirPath.push_back(strPath);
// }

// void do_lc(const char *path)
// {
//     assert(path);

//     DIR *p_dir;
//     struct dirent *p_next;
//     vector<string> list;
//     // 0: file; 1:folder;
//     int flag = is_file(path);
//     if (flag == 0)
//     {
//         // 文件
//         int *lines = new int[3];
//         lines = compute_line_number(path);
//         string pathName = path;
//         // print(lines, pathName, 0);

//         line_printed[counter] = lines;
//         path_printed[counter] = pathName;
//         counter++;
//     }
//     else if (flag == 1)
//     {
//         // 文件夹
//         if ((p_dir = opendir(path)) == NULL)
//         {
//             perror("opendir error");
//             exit(1);
//         }

//         if ((dirFd = dirfd(p_dir)) == -1)
//         {
//             perror("dirfd error");
//             exit(0);
//         }

//         while ((p_next = readdir(p_dir)) != NULL)
//         {
//             // cout << "p_next->d_name: " << p_next->d_name << endl;
//             // process option -a
//             string temp = path;
//             string connector = "/";
//             if (temp.back() == '/')
//                 connector = "";
//             string pathname = temp + connector + p_next->d_name;

//             if (is_file(pathname.data()) == 1)
//             {
//                 // 当不采用-r模式时，所有文件夹都跳过
//                 // 当采用-r模式时，除了"."和".."之外的文件夹都跳过
//                 if (g_option[OPT_r] == 0 || (strcmp(p_next->d_name, ".") == 0 || strcmp(p_next->d_name, "..") == 0))
//                 {
//                     continue;
//                 }
//             }
//             list.push_back(pathname);
//         }
//         for (int i = 0; i < list.size(); i++)
//         {
//             do_lc(list[i].data());
//         }
//     }
// }
